﻿// -------------------------------------------------------------------------
//    @FileName         :    NFLoginModule.cpp
//    @Author           :    gaoyi
//    @Date             :    24-8-13
//    @Email            :    445267987@qq.com
//    @Module           :    NFLoginModule
//
// -------------------------------------------------------------------------

#include "NFLoginModule.h"

#include <NFEventDisp.h>
#include <NFLogicConfig.h>
#include <NFLoginUtil.h>
#include <NFMapPart.h>
#include <NFNoviceGuidePart.h>
#include <NFOnlineUtil.h>
#include <NFPlayer.h>
#include <NFPlayerMgr.h>
#include <NFPlayerPacketSendUtil.h>
#include <NFPlayerUtil.h>
#include <NFSessionUtil.h>
#include <NFTransGetRoleList.h>
#include <VersionControlDescEx.h>
#include <DescStore/ZoneMergeZoneMergeDesc.h>
#include <NFComm/NFObjCommon/NFTransBase.h>

#include "NFPacketSendUtil.h"
#include "NFSession.h"
#include "NFTransCreateRole.h"
#include "NFWhiteListCache.h"
#include "proto_svr_common.pb.h"
#include "proto_svr_sns.pb.h"
#include "NFServerComm/NFServerCommon/NFIServerMessageModule.h"

NFLoginModule::NFLoginModule(NFIPluginManager* p) : NFLogicDynamicModule(p)
{
}

NFLoginModule::~NFLoginModule()
{
}

int NFLoginModule::Awake()
{
    RegisterClientMessage(NF_ST_LOGIC_SERVER, proto_ff::E_CS_HEARTBEAT_REQ);
    RegisterClientMessage(NF_ST_LOGIC_SERVER, proto_ff::E_CS_LOGIN_REQ, true);
    RegisterClientMessage(NF_ST_LOGIC_SERVER, proto_ff::E_CS_LOG_CHECK_POINT_REQ);
    RegisterClientMessage(NF_ST_LOGIC_SERVER, proto_ff::E_CS_GETROLE_REQ);
    RegisterClientMessage(NF_ST_LOGIC_SERVER, proto_ff::E_CS_CHANGE_AVATAR_REQ);
    RegisterClientMessage(NF_ST_LOGIC_SERVER, proto_ff::E_CS_BATTLESVR_RTT_REQ);
    RegisterClientMessage(NF_ST_LOGIC_SERVER, proto_ff::E_CS_NOVICE_GUIDE_GET_REQ);
    RegisterClientMessage(NF_ST_LOGIC_SERVER, proto_ff::E_CS_NOVICE_GUIDE_SET_REQ);
    RegisterClientMessage(NF_ST_LOGIC_SERVER, proto_ff::E_CS_SELECT_HERO_REQ);
    RegisterClientMessage(NF_ST_LOGIC_SERVER, proto_ff::E_CS_LINEUP_CANCEL_REQ);
    RegisterClientMessage(NF_ST_LOGIC_SERVER, proto_ff::E_CS_ROLE_INFO_MODIFY_REQ);
    RegisterClientMessage(NF_ST_LOGIC_SERVER, proto_ff::E_CS_CREATE_ROLE_REQ);
    RegisterClientMessage(NF_ST_LOGIC_SERVER, proto_ff::E_CS_DELETE_ROLE_REQ);
    RegisterClientMessage(NF_ST_LOGIC_SERVER, proto_ff::E_CS_LOGIN_FAST_ROLE_REQ);
    RegisterClientMessage(NF_ST_LOGIC_SERVER, proto_ff::E_CS_STATE_LEAVE_REQ);
    RegisterClientMessage(NF_ST_LOGIC_SERVER, proto_ff::E_CS_MSDK_REFRESH_REQ);
    RegisterClientMessage(NF_ST_LOGIC_SERVER, proto_ff::E_CS_FAN_TYPE_REPORT_REQ);
    RegisterClientMessage(NF_ST_LOGIC_SERVER, proto_ff::E_CS_MSDK_CHECK_ACCESS_TOKEN_REQ);
    RegisterClientMessage(NF_ST_LOGIC_SERVER, proto_ff::E_CS_PRELOGIN_UID_REQ);

    RegisterServerMessage(NF_ST_LOGIC_SERVER, proto_ff::E_SG_ROLE_LOGIN_NTF);
    return 0;
}

int NFLoginModule::OnHandleClientMessage(NFDataPackage& packet, NFSession* pSession, const proto_ff::Proto_CSReq& req)
{
    CHECK_NULL(0, pSession);
    if (!m_pObjPluginManager->IsInited(NF_ST_LOGIC_SERVER))
    {
        NFLogError(NF_LOG_DEFAULT, packet.nParam1, "Logic Server not inited, drop client msg:{}", packet.ToString());
        return -1;
    }

    if (m_pObjPluginManager->IsServerStopping())
    {
        NFLogError(NF_LOG_DEFAULT, packet.nParam1, "Logic Server is Stopping, drop client msg:{}", packet.ToString());
        return proto_ff::ERR_CODE_SERVER_IS_STOPPING;
    }

    int iRetCode = 0;
    switch (packet.nMsgId)
    {
        case proto_ff::E_CS_HEARTBEAT_REQ:
        {
            iRetCode = OnHandleHeartBeat(packet, pSession, req);
            break;
        }
        case proto_ff::E_CS_LOGIN_REQ:
        {
            iRetCode = OnHandleAccLogin(packet, pSession, req);
            break;
        }
        case proto_ff::E_CS_CREATE_ROLE_REQ:
        {
            iRetCode = OnHandleCreateRoleReq(packet, pSession, req);
            break;
        }
        case proto_ff::E_CS_BATTLESVR_RTT_REQ:
        {
            iRetCode = OnHandleRttSetClockReq(packet, pSession, req);
            break;
        }
        case proto_ff::E_CS_LOG_CHECK_POINT_REQ:
        {
            iRetCode = OnHandleLogCheckPointReq(packet, pSession, req);
            break;
        }
        case proto_ff::E_CS_LINEUP_CANCEL_REQ:
        {
            iRetCode = OnHandleLineUpCancelReq(packet, pSession, req);
            break;
        }
        case proto_ff::E_CS_DELETE_ROLE_REQ:
        {
            iRetCode = OnHandleDeleteRoleReq(packet, pSession, req);
            break;
        }
        case proto_ff::E_CS_GETROLE_REQ:
        {
            iRetCode = OnHandleRoleLoginReq(packet, pSession, req);
            break;
        }
        case proto_ff::E_CS_FAN_TYPE_REPORT_REQ:
        {
            iRetCode = OnHandleFanTypeReportReq(packet, pSession, req);
            break;
        }
        case proto_ff::E_CS_NOVICE_GUIDE_GET_REQ:
        {
            iRetCode = OnHandleNoviceGuideGetReq(packet, pSession, req);
            break;
        }
        case proto_ff::E_CS_NOVICE_GUIDE_SET_REQ:
        {
            iRetCode = OnHandleNoviceGuideSetReq(packet, pSession, req);
            break;
        }
        case proto_ff::E_CS_STATE_LEAVE_REQ:
        {
            iRetCode = OnHandleStateLeaveReq(packet, pSession, req);
            break;
        }
        default: NFLogError(NF_LOG_DEFAULT, 0, "not handle msg:{}", packet.nMsgId);
    }

    return iRetCode;
}

int NFLoginModule::OnHandleHeartBeat(NFDataPackage& packet, NFSession* pSession, const proto_ff::Proto_CSReq& req)
{
    CHECK_NULL(0, pSession);
    pSession->SetLastActiveTime(NF_ADJUST_TIMENOW());

    proto_ff::Proto_CSRsp rsp;
    proto_ff::Proto_RoleTimeValue* timevalue = rsp.mutable_heart_beat()->mutable_time_prop();
    if (req.has_heart_beat())
    {
        timevalue->set_value(req.heart_beat().reserve());
    }
    else
    {
        timevalue->set_value(0);
    }

    timevalue->set_next_add_value_time(NFGetSecondTime());
    if (req.has_timestamp())
    {
        rsp.set_timestamp(req.timestamp());
    }

    int iRetCode = NFPacketSendUtil::SendToClient(pSession, proto_ff::E_CS_HEARTBEAT_RSP, &rsp);
    CHECK_RET(iRetCode, "CGameSvrPacketSendUtil::SendToClient Failed");

    LOGSVR_TRACE("HeartBeat ConnIdx:" << pSession->GetConnIndex() << " time:" << pSession->GetLastActiveTime());

    return iRetCode;
}

/**
 * @brief 检查并处理登录请求
 *
 * 此函数负责验证客户端的登录请求，包括版本号、登录区域 ID 等校验，并根据校验结果执行相应的处理逻辑。
 * 如果校验通过，还会设置会话的相关状态信息。
 *
 * @param pSession 当前会话对象的指针
 * @param message 客户端发送的登录请求消息
 * @return 0 表示成功，其他值为错误码
 *
 * @note 主要处理逻辑：
 *       1. 检查会话对象是否为空；
 *       2. 校验客户端版本号与资源版本号；
 *       3. 校验登录区域 ID 是否匹配；
 *       4. 根据登录请求设置会话的区域 ID 和招募状态；
 *       5. 判断是否需要排队并处理排队逻辑。
 *
 * @warning 确保会话对象和登录请求消息的有效性，避免空指针或非法数据。
 */
int NFLoginModule::CheckAndHandleLogin(NFSession* pSession, const proto_ff::Proto_CSLoginReq& message)
{
    int iRetCode = 0;
    CHECK_NULL(0, pSession);
    // 临时修改：版本号与平台号交换
    proto_ff::Proto_PlatType platType = message.client_info().plat_type();
    if (platType == proto_ff::E_PLAT_NONE)
    {
        platType = static_cast<proto_ff::Proto_PlatType>(pSession->GetClientInfo()->plat_type);
    }

    iRetCode = CheckClientVersion(platType, message.client_info().client_version(), message.client_info().client_res_version());
    CHECK_ERR(pSession->GetUIN(), iRetCode, "client version too old!");

    iRetCode = CheckLoginZoneId(message.zone_id());
    CHECK_ERR(pSession->GetUIN(), iRetCode, "login zone id is not match! login zoneid:{}", message.zone_id());

    if (message.has_zone_id() && message.zone_id() != 0)
    {
        pSession->SetZoneAreaID(message.zone_id());
    }

    pSession->SetRecruit(message.is_recruit());
    if (message.is_recruit())
    {
        pSession->SetInviteOpenID(message.invite_openid().c_str());
        pSession->SetInvitedSOpenID(message.invited_sopenid().c_str());
    }
    return 0;
}

int NFLoginModule::CheckWhiteAndRegChannel(NFSession* pSession, const proto_ff::Proto_CSLoginReq& message)
{
    int iRetCode = 0;
    CHECK_NULL(0, pSession);
    int iSessionId = pSession->GetGlobalId();
    if (NFLogicConfig::Instance()->WhiteListLogin())
    {
        proto_ff::tbWriteList tbWritelist;
        tbWritelist.set_account_id(pSession->GetAccountID());

        iRetCode = FindModule<NFIServerMessageModule>()->GetRpcSelectObjService(NF_ST_LOGIC_SERVER, pSession->GetUIN(), tbWritelist);

        pSession = NFSessionUtil::GetSessionObj(iSessionId);
        CHECK_EXPR(pSession, -1, "CServerUtil::GetSessionObj Failed ID:{}", iSessionId);

        bool bIsGetRole = true;
        if (iRetCode != 0)
        {
            bIsGetRole = false;

            tbWriteList stWhiteList;
            stWhiteList.account_id = pSession->GetAccountID();

            if (NFWhiteListCache::Instance()->IsInWhiteList(&stWhiteList))
            {
                switch (pSession->GetPlatformType())
                {
                    case proto_ff::E_Account_Type_QQ:
                    case proto_ff::E_Account_Type_Wechat:
                    case proto_ff::E_Account_Type_Guest:
                        bIsGetRole = true;
                        break;
                    default:
                        bIsGetRole = true;
                        break;
                }
            }

            if (NFLogicConfig::Instance()->IsRegChannelOpen())
            {
                if (NFLogicConfig::Instance()->CheckRegChannelWhite(message.client_info().login_channel_str()))
                {
                    bIsGetRole = true;
                }
            }
        }
        else
        {
            LOGSVR_TRACE("tb_writelist.account_id:" << tbWritelist.account_id().c_str() << ",tb_writelist.account_pwd:" << tbWritelist.account_pwd().c_str());
            LOGSVR_TRACE("account_id:" << pSession->GetAccountID() << ",account_pwd:" << message.account_pwd());

            bool bCheckAccount = tbWritelist.account_id() == pSession->GetAccountID();

            bool bCheckPsw = true;
            switch (pSession->GetPlatformType())
            {
                case proto_ff::E_Account_Type_Guest:
                    break;
                default:
                    bCheckPsw = tbWritelist.account_pwd() == message.account_pwd();
                    break;
            }

            if (!bCheckAccount || !bCheckPsw)
            {
                bIsGetRole = false;
                if (NFLogicConfig::Instance()->IsRegChannelOpen())
                {
                    if (NFLogicConfig::Instance()->CheckRegChannelWhite(message.client_info().login_channel_str()))
                    {
                        bIsGetRole = true;
                    }
                }
            }
        }

        if (bIsGetRole)
        {
            return 0;
        }
        else
        {
            proto_ff::Proto_CSRsp rsp;
            proto_ff::Proto_CSAccountErrorRsp* accountErrorRsp = rsp.mutable_account_error_rsp();
            accountErrorRsp->set_account_or_pwd_error(true);

            NFPacketSendUtil::SendToClient(pSession, proto_ff::E_CS_ACCOUNT_ERROR_RSP, &rsp);
        }

        return iRetCode;
    }
    else
    {
        if (NFLogicConfig::Instance()->IsRegChannelOpen())
        {
            CHECK_EXPR(NFLogicConfig::Instance()->CheckRegChannelWhite(message.client_info().login_channel_str().c_str()), proto_ff::ERR_CODE_LOGIN_REG_CHANNEL_NOT_LOGIN, "reg channel err:{}", message.client_info().login_channel_str());
        }
    }
    return 0;
}

/**
 * @brief 处理客户端登录请求的函数
 *
 * 此函数负责处理客户端发送的登录请求消息，执行一系列校验和逻辑处理，
 * 包括检查登录信息的合法性、白名单和注册渠道的校验，以及角色列表的获取。
 *
 * @param packet 包含客户端发送的登录请求数据包
 * @param pSession 当前会话对象的指针，用于标识和管理与客户端的会话
 * @param req 客户端发送的请求消息，包含登录请求的具体内容
 *
 * @return int 返回处理结果的状态码。通常返回0表示处理成功，非0表示处理失败或错误码
 *
 * @note
 * - 确保会话对象和请求消息的有效性，避免空指针或非法数据。
 * - 校验逻辑包括登录信息的合法性检查和白名单/注册渠道的校验。
 * - 如果校验通过，将初始化并处理角色列表的获取事务。
 * - 该函数的实现应遵循安全编码实践，避免信息泄露或被恶意利用。
 */
int NFLoginModule::OnHandleAccLogin(NFDataPackage& packet, NFSession* pSession, const proto_ff::Proto_CSReq& req)
{
    int iRetCode = 0;
    CHECK_NULL(0, pSession);

    // 检查请求消息是否包含登录信息
    CHECK_EXPR(req.has_login(), -1, "not has login");
    const proto_ff::Proto_CSLoginReq& message = req.login();

    // 校验并处理登录信息
    iRetCode = CheckAndHandleLogin(pSession, message);
    CHECK_ERR(pSession->GetUIN(), iRetCode, "CheckLogin Failed Session:{}", pSession->GetGlobalId());

    // 校验白名单和注册渠道
    iRetCode = CheckWhiteAndRegChannel(pSession, message);
    CHECK_ERR(pSession->GetUIN(), iRetCode, "CheckWhiteAndRegChannel Failed Session:{}", pSession->GetGlobalId());

    // 打印调试信息
    LOGSVR_DEBUG("session: " << pSession->GetGlobalId() << " is from recruit: " << pSession->IsRecruit() << " open id: " << pSession->GetInviteOpenID() << " sopen id: " << pSession->GetInvitedSOpenID() << " session open id: " << pSession->GetOpenID());

    // 创建并初始化获取角色列表的事务
    NFTransGetRoleList* pTransGetRoleList = NFTransGetRoleList::CreateTrans();
    CHECK_EXPR(pTransGetRoleList, -1, "NFTransMng::Instance() CreateTrans {} Failed", EOT_TRANS_LOGIC_GET_ROLELIST);

    iRetCode = pTransGetRoleList->Init(pSession, proto_ff::E_CS_LOGIN_REQ, 0);
    CHECK_RET(iRetCode, "pTransLogin->Init Failed Session:{}", pSession->GetGlobalId());

    // 处理角色列表获取请求
    iRetCode = pTransGetRoleList->ProcessCSMsgReq(&message);
    CHECK_ERR_AND_FIN_TRANS(iRetCode, pTransGetRoleList, "pTransGetRoleList->ProcessCSMsgReq Failed MsgInfo");

    return iRetCode;
}

int NFLoginModule::CheckClientVersion(proto_ff::Proto_PlatType ePlatType, std::string strClientVersion, std::string strResVersion) const
{
    if (false == NFLogicConfig::Instance()->IsCheckClientVersion())
    {
        return 0;
    }

    //check min version
    VersionDesc stClientVer;
    VersionControlDescEx::ParseVersion(strClientVersion.c_str(), stClientVer);
    LOGSVR_TRACE("client version:" << strClientVersion.c_str() << " Parse result:" << stClientVer.big_ver << "," << stClientVer.mid_ver << "," << stClientVer.min_ver << "," << stClientVer.build_cnt);

    VersionDesc stResVer;
    VersionControlDescEx::ParseVersion(strResVersion.c_str(), stResVer);
    LOGSVR_TRACE("client res version:" << strResVersion.c_str() << " Parse result:" << stResVer.big_ver << "," << stResVer.mid_ver << "," << stResVer.min_ver << "," << stResVer.build_cnt);

    int iWorldId = NFServerIDUtil::GetRegionID(m_pObjPluginManager->GetAppID());
    int iZoneAreaId = NFServerIDUtil::GetZoneAreaID(m_pObjPluginManager->GetAppID());
    auto pVersionControlDesc = VersionControlDescEx::Instance()->GetDescByWorldIdZoneIdPlatType(iWorldId, iZoneAreaId, ePlatType);
    LOGSVR_TRACE("version ePlatType : " << ePlatType);
    if (pVersionControlDesc)
    {
        LOGSVR_TRACE("pVerionControlDesc is exist: min_cli_ver" << pVersionControlDesc->minCliVer.ToString() << "max cli ver" << pVersionControlDesc->maxCliVer.ToString());
        if (CompareVersion(pVersionControlDesc->min_cli_ver, stClientVer) < 0)
        {
            LOGSVR_TRACE("client version:" << strClientVersion.c_str() << " Config min client version:" << pVersionControlDesc->minCliVer.ToString());
            return proto_ff::ERR_CODE_KICKOFF_OLD_CLIENT_VERSION;
        }

        if (pVersionControlDesc->is_max_cli_limit && CompareVersion(stClientVer, pVersionControlDesc->max_cli_ver) < 0)
        {
            LOGSVR_TRACE("client version:" << strClientVersion.c_str() << " Config max client version:" << pVersionControlDesc->maxCliVer.ToString());
            return proto_ff::ERR_CODE_KICKOFF_OLD_CLIENT_VERSION;
        }

        if (CompareVersion(pVersionControlDesc->min_res_ver, stResVer) < 0)
        {
            LOGSVR_TRACE("client res version:" << strResVersion.c_str() << " Config min client res version:" << pVersionControlDesc->minResVer.ToString());
            return proto_ff::ERR_CODE_KICKOFF_OLD_CLIENT_VERSION;
        }

        if (pVersionControlDesc->is_max_res_limit && CompareVersion(stResVer, pVersionControlDesc->max_res_ver) < 0)
        {
            LOGSVR_TRACE("client version:" << strResVersion.c_str() << " Config max client version:" << pVersionControlDesc->maxResVer.ToString());
            return proto_ff::ERR_CODE_KICKOFF_OLD_CLIENT_VERSION;
        }
    }

    return 0;
}

int NFLoginModule::CheckLoginZoneId(int iLoginZoneId) const
{
    int iZoneAreaId = NFServerIDUtil::GetZoneAreaID(m_pObjPluginManager->GetAppID());
    if (iLoginZoneId == iZoneAreaId)
    {
        return 0;
    }
    else if (NFLogicConfig::Instance()->NotCheckZone())
    {
        return 0;
    }
    else
    {
        auto pZoneDesc = ZoneMergeZoneMergeDesc::Instance()->GetDesc(iLoginZoneId);
        if (pZoneDesc)
        {
            return 0;
        }
    }

    return proto_ff::ERR_CODE_LOGIN_ZONE_ID_INVALID;
}

int NFLoginModule::CompareVersion(const VersionDesc& stLeftVer, const VersionDesc& stRightVer)
{
    //big ver
    if (stRightVer.big_ver > stLeftVer.big_ver)
    {
        return 1;
    }
    else
        if (stRightVer.big_ver < stLeftVer.big_ver)
        {
            return -1;
        }

    //mid ver
    if (stRightVer.mid_ver > stLeftVer.mid_ver)
    {
        return 1;
    }
    else
        if (stRightVer.mid_ver < stLeftVer.mid_ver)
        {
            return -1;
        }

    //min ver
    if (stRightVer.min_ver > stLeftVer.min_ver)
    {
        return 1;
    }
    else
        if (stRightVer.min_ver < stLeftVer.min_ver)
        {
            return -1;
        }

    if (stRightVer.build_cnt > stLeftVer.build_cnt)
    {
        return 1;
    }
    else
        if (stRightVer.build_cnt < stLeftVer.build_cnt)
        {
            return -1;
        }

    return 0;
}

int NFLoginModule::CreateRoleError(NFSession* pSession, int errCode)
{
    proto_ff::Proto_CSRsp oCsRsp;
    proto_ff::Proto_CSCreateRoleRsp* pCreateRoleRsp = oCsRsp.mutable_create_role_rsp();

    pCreateRoleRsp->set_result(errCode);

    return NFPacketSendUtil::SendToClient(pSession, proto_ff::E_CS_CREATE_ROLE_RSP, &oCsRsp);
}

int NFLoginModule::OnHandleCreateRoleReq(NFDataPackage& packet, NFSession* pSession, const proto_ff::Proto_CSReq& req)
{
    CHECK_NULL(0, pSession);
    CHECK_EXPR(req.has_create_role_req(), -2, "not has create_role_req");

    if (!pSession->IsLogin())
    {
        CreateRoleError(pSession, -1);
        return -1;
    }

    NFTransCreateRole* pTransCreateRole = NFTransCreateRole::CreateTrans();
    CHECK_NULL(0, pTransCreateRole);

    int iRetCode = pTransCreateRole->Init(pSession, proto_ff::E_CS_CREATE_ROLE_REQ, 0);
    CHECK_RET(iRetCode, "pTransLogin->Init Failed Session:{}", pSession->GetGlobalId());

    iRetCode = pTransCreateRole->ProcessCSMsgReq(&req);
    CHECK_ERR_AND_FIN_TRANS(iRetCode, pTransCreateRole, "pTransCreateRole->ProcessCSMsgReq Failed MsgInfo");

    return 0;
}

int NFLoginModule::OnHandleRttSetClockReq(NFDataPackage& packet, NFSession* pSession, const proto_ff::Proto_CSReq& pstCsMsgReq)
{
    int iRetCode = 0;

    CHECK_EXPR(pstCsMsgReq.has_rtt_set_clock_req(), -1, "");

    const proto_ff::Proto_CSRTTSetClockReq& rttSetClockReq = pstCsMsgReq.rtt_set_clock_req();

    proto_ff::Proto_CSRsp rsp;
    proto_ff::Proto_CSRTTSetClockRsp& setClockRsp = *rsp.mutable_rtt_set_clock_rsp();
    setClockRsp.set_seq(rttSetClockReq.seq());
    setClockRsp.set_time_now(NF_ADJUST_TIMENOW_MS());
    NFPacketSendUtil::SendToClient(pSession, proto_ff::E_CS_BATTLESVR_RTT_RSP, &rsp);

    return iRetCode;
}

int NFLoginModule::OnHandleLogCheckPointReq(NFDataPackage& packet, NFSession* pSession, const proto_ff::Proto_CSReq& req)
{
    NFEventDisp::OnSessionLogCheckPoint(pSession, req.client_log_check_point_req());

    proto_ff::Proto_CSRsp rsp;
    int iRetCode = NFPacketSendUtil::SendToClient(pSession, proto_ff::E_CS_LOG_CHECK_POINT_RSP, &rsp);
    CHECK_RET(iRetCode, "CGameSvrPacketSendUtil::SendToClient Failed");

    return iRetCode;
}

int NFLoginModule::OnHandleDeleteRoleReq(NFDataPackage& packet, NFSession* pSession, const proto_ff::Proto_CSReq& req)
{
    CHECK_NULL(0, pSession);
    int iRetCode = 0;

    /*const proto_ff::Proto_CSDeleteRoleReq& oDeleteRoleReq = req.del_role_req();

    NFPlayerAccount* pPlayerAccount = NFPlayerMgr::Instance()->FindAccount(pSession->GetZoneID(), pSession->GetUIN());
    CHECK_NULL(0, pPlayerAccount);

    RoleOne stRoleOne;
    iRetCode = pPlayerAccount->GetRoleOne(oDeleteRoleReq.role_id(), &stRoleOne);
    CHECK_RET(iRetCode, "Find Role Failed!");

    iRetCode = pPlayerAccount->DeleteRole(oDeleteRoleReq.role_id());
    CHECK_RET(iRetCode, "Delete Role Failed!");

    NFEventDisp::OnPlayerDelete(pSession, &stRoleOne);

    //response to client
    proto_ff::Proto_CSRsp rsp;
    proto_ff::Proto_CSDeleteRoleRsp* pDelRoleRsp = rsp.mutable_del_role_rsp();

    tbRoleList* pRoleList = pPlayerAccount->GetRoleList();
    for (auto iter = pRoleList->role_data.role_list.begin(); iter != pRoleList->role_data.role_list.end(); ++iter)
    {
        proto_ff::RoleOne* pRoleOne = pDelRoleRsp->add_role_list();
        CHECK_NULL(0, pRoleOne);

        iter->second.ToPb(pRoleOne);
    }

    iRetCode = NFPacketSendUtil::SendToClient(pSession, proto_ff::E_CS_DELETE_ROLE_RSP, &rsp);
    CHECK_RET(iRetCode, "CGameSvrPacketSendUtil::SendToClient Failed");

    //kick player
    NFPlayer* pPlayer = NFPlayerUtil::GetPlayerByRoleID(oDeleteRoleReq.role_id());
    if (pPlayer)
    {
        if (pPlayer->GetClientSession() == pSession)
        {
        }
        else
        {
            NFOnlineUtil::KickOff(oDeleteRoleReq.role_id(), proto_ff::ERR_CODE_ROLE_KICKOFF_BY_DELETE_ROLE);
        }
    }*/

    return iRetCode;
}

int NFLoginModule::OnHandleLineUpCancelReq(NFDataPackage& packet, NFSession* pSession, const proto_ff::Proto_CSReq& req)
{
    CHECK_NULL(0, pSession);

    proto_ff::Proto_CSRsp rsp;
    rsp.mutable_lineup_cancel_rsp();

    NFPacketSendUtil::SendToClient(pSession, proto_ff::E_CS_LINEUP_CANCEL_RSP, &rsp);
    return 0;
}

int NFLoginModule::OnHandleRoleLoginReq(NFDataPackage& packet, NFSession* pSession, const proto_ff::Proto_CSReq& req)
{
    int iRetCode = 0;
    CHECK_NULL(0, pSession);

    const proto_ff::Proto_CSGetRoleReq oCsGetRoleReq = req.get_role();
    uint64_t ullRoleId = oCsGetRoleReq.role_id();
    if (ullRoleId == 0)
    {
        CHECK_ERR(0, -1, "role id is 0, please check client msg:{}", oCsGetRoleReq.DebugString());
    }

    if (pSession->GetPlayer())
    {
        if (!pSession->GetPlayer()->GetRoleID() == ullRoleId)
        {
            CHECK_ERR(ullRoleId, proto_ff::ERR_CODE_CANNOT_LOGIN_DIFF_ROLE_BY_SAME_SESSION, "player:{} already login role:{}, cant' login role:{}", pSession->GetAccountID(), pSession->GetPlayer()->GetRoleID(), ullRoleId);
        }
    }

    iRetCode = NFLoginUtil::SendTransGetRole(pSession, oCsGetRoleReq);
    CHECK_ERR(ullRoleId, iRetCode, "SendTransGetRole Failed, role id:{}", ullRoleId);

    return 0;
}

int NFLoginModule::OnHandleFanTypeReportReq(NFDataPackage& packet, NFSession* pSession, const proto_ff::Proto_CSReq& req)
{
    /*NFPlayerAccount* pPlayerAccount = NFPlayerMgr::Instance()->FindAccount(pSession->GetZoneID(), pSession->GetUIN());
    CHECK_NULL(0, pPlayerAccount);

    tbRoleList* pRoleList = pPlayerAccount->GetRoleList();
    if (pRoleList->role_data.role_list.size() == 0 || pRoleList->fan_type == 0)
    {
        pPlayerAccount->OnReportFanType(req.fan_type_report_req().type());
    }*/
    return 0;
}

int NFLoginModule::OnHandleNoviceGuideGetReq(NFDataPackage& packet, NFSession* pSession, const proto_ff::Proto_CSReq& req)
{
    int iRetCode = 0;
    CHECK_NULL(0, pSession);

    NFPlayer* pPlayer = pSession->GetPlayer();
    CHECK_NULL(0, pPlayer);

    auto pNoviceGuidePart = pPlayer->GetPart<NFNoviceGuidePart>(PART_NOVICEGUIDE);
    CHECK_NULL(pPlayer->GetRoleID(), pNoviceGuidePart);

    proto_ff::Proto_CSRsp rsp;
    pNoviceGuidePart->GetData().ToPb(rsp.mutable_novice_guide_get_rsp());
    NFPacketSendUtil::SendToClient(pSession, proto_ff::E_CS_NOVICE_GUIDE_GET_RSP, &rsp);
    return iRetCode;
}

int NFLoginModule::OnHandleNoviceGuideSetReq(NFDataPackage& packet, NFSession* pSession, const proto_ff::Proto_CSReq& req)
{
    int iRetCode = 0;
    CHECK_NULL(0, pSession);

    CHECK_EXPR(req.has_novice_guide_set_req(), -1, "");

    const proto_ff::RoleNoviceGuide& noviceGuideSetReq = req.novice_guide_set_req();

    NFPlayer* pPlayer = pSession->GetPlayer();
    CHECK_NULL(0, pPlayer);

    auto pNoviceGuidePart = pPlayer->GetPart<NFNoviceGuidePart>(PART_NOVICEGUIDE);
    CHECK_NULL(pPlayer->GetRoleID(), pNoviceGuidePart);

    pNoviceGuidePart->GetData().FromPb(noviceGuideSetReq);

    proto_ff::Proto_CSRsp rsp;
    pNoviceGuidePart->GetData().ToPb(rsp.mutable_novice_guide_get_rsp());
    NFPacketSendUtil::SendToClient(pSession, proto_ff::E_CS_NOVICE_GUIDE_SET_RSP, &rsp);

    return iRetCode;
}

int NFLoginModule::OnHandleStateLeaveReq(NFDataPackage& packet, NFSession* pSession, const proto_ff::Proto_CSReq& req)
{
    int iRetCode = 0;
    CHECK_NULL(0, pSession);

    const proto_ff::Proto_CSStateLeaveReq& oStateLeaveReq = req.state_leave_req();

    NFPlayer* pPlayer = pSession->GetPlayer();
    CHECK_NULL(0, pPlayer);

    auto pMapPart = pPlayer->GetPart<NFMapPart>(PART_MAP);
    CHECK_NULL(pPlayer->GetRoleID(), pMapPart);

    bool bSet = pMapPart->IsStateLeave();
    if (bSet != oStateLeaveReq.state_leave())
    {
        pMapPart->SetStateLeave(oStateLeaveReq.state_leave());
        pMapPart->MarkDirty();

        /*CPlayerTeam* pTeam = pPlayer->GetPlayerTeam();
        if (pTeam)
        {
            TEAMMEMBER* pMember = pTeam->FindMember(pPlayer->GetRoleID());
            if (pMember)
            {
                pMember->is_leave_state = oStateLeaveReq.state_leave();
            }
            CPlayerTeamPacketUtil::MulticastTeamInfo_ToClient(pTeam, pPlayer->GetRoleID(), proto_ff::CS_TEAM_NOTIFY_EVENT_STATE_LEAVE_CHG);
        }*/

        //rsp
        proto_ff::Proto_CSRsp rsp;
        proto_ff::Proto_CSStateLeaveRsp* pStateLeaveRsp = rsp.mutable_state_leave_rsp();
        pStateLeaveRsp->set_state_leave(oStateLeaveReq.state_leave());

        NFPacketSendUtil::SendToClient(pSession, proto_ff::E_CS_STATE_LEAVE_RSP, &rsp);
    }

    return 0;
}

int NFLoginModule::OnHandleServerMessage(uint32_t msgId, NFDataPackage& packet, uint64_t param1, uint64_t param2)
{
    if (!m_pObjPluginManager->IsInited(NF_ST_LOGIC_SERVER))
    {
        NFLogError(NF_LOG_DEFAULT, packet.nParam1, "Logic Server not inited, drop client msg:{}", packet.ToString());
        return -1;
    }

    if (m_pObjPluginManager->IsServerStopping())
    {
        NFLogError(NF_LOG_DEFAULT, packet.nParam1, "Logic Server is Stopping, drop client msg:{}", packet.ToString());
        return -1;
    }

    int iRetCode = 0;
    switch (packet.nMsgId)
    {
        case proto_ff::E_SG_ROLE_LOGIN_NTF:
        {
            iRetCode = OnHandleRoleLoginNtf(msgId, packet, packet.nParam1, packet.nParam2);
            break;
        }
        default:
        {
            NFLogError(NF_LOG_DEFAULT, 0, "Server MsgId:{} Register, But Not Handle, Package:{}", packet.nMsgId, packet.ToString());
            break;
        }
    }
    return iRetCode;
}

int NFLoginModule::OnHandleRoleLoginNtf(uint32_t msgId, NFDataPackage& packet, uint64_t param1, uint64_t param2)
{
    proto_ff::Proto_SGRoleLoginNtf ntf;
    CLIENT_MSG_PROCESS_WITH_PRINTF(packet, ntf);

    for (int i = 0; i < ntf.role_id_size(); i++)
    {
        uint64_t roleId = ntf.role_id(i);
        NFPlayer* pPlayer = NFPlayerMgr::Instance()->GetPlayer(roleId);
        if (!pPlayer)
            continue;

        //通知结果
        proto_ff::Proto_CSRsp pkg;
        proto_ff::Proto_CSLoginNtf* pNtf = pkg.mutable_login_ntf();
        pNtf->set_role_id(ntf.target_role_id());
        pNtf->set_moudle(ntf.moudle());
        NFPacketSendUtil::SendToClient(pPlayer, proto_ff::E_CS_SNS_LOGIN_NTF, &pkg);
    }
    return 0;
}
